package eolympics;

import java.io.IOException;
import java.util.List;

import minigames.IMiniGame;

import com.google.common.base.Preconditions;

import data.IGameDataReadOnly;
import data.Player;
import eolympics.client.GameClient;
import eolympics.server.GameServer;

public class Game
{
    public final static int             MINIMUM_NR_OF_MINIGAMES = 2;
    public final static String          LOCALHOST               = "127.0.0.1";

    private final GameServer            mGameServer;
    private final GameClient            mGameClient;

    private final IClientEventsListener mClientLostObserver     = new ClientLostObserver();

    public Game(final MiniGamePluginsLoader pMiniGamePluginsLoader, final GameServer pGameServer)
    {
        Preconditions.checkNotNull(pMiniGamePluginsLoader);
        Preconditions.checkNotNull(pGameServer);
        
        mGameServer = pGameServer;

        List<IMiniGame> miniGames = pMiniGamePluginsLoader.loadMiniGamePlugins();

        if( miniGames.size() < MINIMUM_NR_OF_MINIGAMES )
        {
            throw new RuntimeException("only " + miniGames.size() + " mini games loaded, should be " + MINIMUM_NR_OF_MINIGAMES);
        }

        mGameServer.addMiniGamesToServerData(miniGames);

        mGameClient = new GameClient(miniGames, mClientLostObserver);
    }

    public void setClientEventsListener( final IClientEventsListener pGameEventsListener )
    {
        mGameClient.addClientEventsListener(pGameEventsListener);
    }

    public void sendPlayerIsReadyToServer()
    {
        mGameClient.sendPlayerIsReadyToServer();
    }

    public void startAsServer( String pPlayerName )
    {
        mGameServer.start();
        try
        {
            joinGameAt(LOCALHOST, pPlayerName);
        }
        catch( IOException e )
        {
            throw new RuntimeException("Could not start server.", e);
        }
    }

    public void stopGame()
    {
        mGameClient.disconnectFromServer();
        mGameServer.stop();
    }

    public void joinGameAt( final String pServerAddress, final String pPlayerName ) throws IOException
    {
        System.out.println("connect with server at " + pServerAddress + " with name " + pPlayerName);
        mGameClient.joinGameAt(pServerAddress, pPlayerName);
    }

    public boolean isServerRunning()
    {
        return mGameServer.isRunning();
    }

    public IGameDataReadOnly getClientGameData()
    {
        return mGameClient.getGameData();
    }

    public void addAiPlayerToServer( final Player pPlayer )
    {
        mGameServer.addAiPlayer(pPlayer);
    }

    public void removeAiPlayerFromServer( final String pPlayerName )
    {
        mGameServer.removeAiPlayer(pPlayerName);
    }

    private class ClientLostObserver
            implements IClientEventsListener
    {
        @Override
        public void clientConnectionToServerLost()
        {
            stopGame();
        }

        @Override
        public void playerListChanged( IGameDataReadOnly pGameData )
        {
        }

        @Override
        public void gameStateChanged( IGameDataReadOnly pGameData )
        {
        }
    }
}
